
/*
 **  ITSessionDesc.m
 **
 **  Copyright (c) 2002, 2003
 **
 **  Author: Fabian, Ujwal S. Sathyam
 **	     Initial code by Kiichi Kusama
 **
 **  Project: iTerm
 **
 **  Description: keeps track of the address book data.
 **
 **  This program is free software; you can redistribute it and/or modify
 **  it under the terms of the GNU General Public License as published by
 **  the Free Software Foundation; either version 2 of the License, or
 **  (at your option) any later version.
 **
 **  This program is distributed in the hope that it will be useful,
 **  but WITHOUT ANY WARRANTY; without even the implied warranty of
 **  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 **  GNU General Public License for more details.
 **
 **  You should have received a copy of the GNU General Public License
 **  along with this program; if not, write to the Free Software
 **  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#import "ITSessionDesc.h"

// keys for session param dictionary
#define kITSessionName @"Name"					// NSString
#define kITSessionCommand @"Command"				// NSString
#define kITSessionEncoding @"Encoding"  			// NSNumber unsigned int
#define kITSessionTerminalType @"Terminal Type"                 // NSString "xterm", "vt100"

#define kITSessionDirectory @"Directory"			// NSString
#define kITSessionFont @"Font"					// NSFont
#define kITSessionNAFont @"Non-ASCII Font"                      // NSFont
#define kITSessionAntiIdle @"AntiIdle"      			// NSNumber numberWithBool
#define kITSessionAICode @"Idle Code"				// NSNumber numberWithUnsignedInt
#define kITSessionAutoClose @"Auto Close"                       // NSNumber numberWithBool
#define kITSessionDoubleWidth @"Double Width"                   // NSNumber numberWithBool
#define kITSessionDeleteKeyIsBackspace @"DeleteKey"        	// NSNumber numberWithBool
#define kITSessionForeColor @"ForeColor"                        // NSColor
#define kITSessionBackColor @"BackColor"                        // NSColor
#define kITSessionSelectionColor @"SelectionColor"              // NSColor
#define kITSessionBoldColor @"BoldColor"                        // NSColor

#define kITSessionANSIBlackColor @"ANSIBlackColor"		// NSColor
#define kITSessionANSIHiBlackColor @"ANSIHiBlackColor"		// NSColor
#define kITSessionANSIRedColor @"ANSIRedColor"			// NSColor
#define kITSessionANSIHiRedColor @"ANSIHiRedColor"		// NSColor
#define kITSessionANSIGreenColor @"ANSIGreenColor"		// NSColor
#define kITSessionANSIHiGreenColor @"ANSIHiGreenColor"		// NSColor
#define kITSessionANSIYellowColor @"ANSIYellowColor"		// NSColor
#define kITSessionANSIHiYellowColor @"ANSIHiYellowColor"        // NSColor
#define kITSessionANSIBlueColor @"ANSIBlueColor"		// NSColor
#define kITSessionANSIHiBlueColor @"ANSIHiBlueColor"		// NSColor
#define kITSessionANSIMagentaColor @"ANSIMagentaColor"		// NSColor
#define kITSessionANSIHiMagentaColor @"ANSIHiMagentaColor"      // NSColor
#define kITSessionANSICyanColor @"ANSICyanColor"		// NSColor
#define kITSessionANSIHiCyanColor @"ANSIHiCyanColor"		// NSColor
#define kITSessionANSIWhiteColor @"ANSIWhiteColor"		// NSColor
#define kITSessionANSIHiWhiteColor @"ANSIHiWhiteColor"		// NSColor

@interface ITSessionDesc (Private)
+ (NSColor *)highlightColor:(NSColor *)color;
+ (NSDictionary *)defaultSessionParam;
+ (NSDictionary*)addMissingKeys:(NSDictionary*)inDictionary;
- (void)setParams:(NSDictionary*)params;
@end

@implementation ITSessionDesc

- (id)init;
{
    self = [super init];
    
    [self setParams:[ITSessionDesc defaultSessionParam]];
    
    return self;
}

+ (ITSessionDesc*)defaultDesc;
{
    ITSessionDesc* result = [[ITSessionDesc alloc] init];
    
    return [result autorelease];
}

+ (NSString*)defaultShell;
{
    NSString* result = @"tcsh";
    
    char* userShell = getenv("SHELL");
    
    if (userShell)
        result = [NSString stringWithUTF8String:userShell];
    
    return result;
}

+ (NSArray*)terminalTypes;
{
    static NSMutableArray* array=nil;
    
    if (!array)
    {
        array = [[NSMutableArray array] retain];
        
        [array addObject:@"vt100"];
        [array addObject:@"xterm"];
        [array addObject:@"xterm-color"];
        [array addObject:@"rxvt"];
        [array addObject:@"ansi"];
    }
    
    return array;
}

+ (NSString*)defaultLoginCommand;
{
    NSString *shell;
    char *userShell, *thisUser;
    
    if ((thisUser = getenv("USER")) != NULL) 
        shell = [NSString stringWithFormat: @"login -fp %s", thisUser];
    else if ((userShell = getenv("SHELL")) != NULL)
        shell = [NSString stringWithUTF8String: userShell];
    else
        shell = @"/bin/bash --login";
    
    return shell;
}    

- (void)encodeWithCoder:(NSCoder *)aCoder;
{
    // [super encodeWithCoder:aCoder];
    
    [aCoder encodeObject:_params forKey:@"params"];
}

- (id)initWithCoder:(NSCoder *)aDecoder;
{
    self = [super init];
    
    NSDictionary* dict = [aDecoder decodeObjectForKey:@"params"];

    // make sure we contain all the default params (we could be reading from an older versions pref file)
    _params = [[ITSessionDesc addMissingKeys:dict] retain];
    
    return self;
}

- (id)copyWithZone:(NSZone *)zone;
{
    ITMutableSessionDesc *copy = [[ITSessionDesc alloc] init];
    
    [copy setParams:_params];
        
    return copy;
}

- (id)mutableCopyWithZone:(NSZone *)zone;
{
    ITMutableSessionDesc *copy = [[ITMutableSessionDesc alloc] init];
    
    [copy setParams:_params];
        
    return copy;
}

- (void)dealloc;
{
    [_params release];
    [super dealloc];
}

- (NSString*)name;
{
    return [_params objectForKey:kITSessionName];
}

- (NSString*)command;
{
    return [_params objectForKey:kITSessionCommand];
}

- (unsigned)encoding;
{
    return (unsigned) [[_params objectForKey:kITSessionEncoding] intValue];
}

- (NSString*)terminalType;
{
    return [_params objectForKey:kITSessionTerminalType];
}

- (NSString*)directory;
{
    NSString* result = [_params objectForKey:kITSessionDirectory];
    
    // if directory is blank or nil, set to home
    if (!result || ![result length])
        result = @"~";

    return result;
}

- (NSFont*)font;
{
    return [_params objectForKey:kITSessionFont];
}

- (NSFont*)nonASCIIFont;
{
    return [_params objectForKey:kITSessionNAFont];
}

- (BOOL)isIdleKeepAliveEnabled;
{
    return [[_params objectForKey:kITSessionAntiIdle] boolValue];
}

- (unsigned char)idleKeepAliveCharacterCode;
{
    return [[_params objectForKey:kITSessionAICode] unsignedIntValue];
}

- (BOOL)closeSessionWhenEnds;
{
    return [[_params objectForKey:kITSessionAutoClose] boolValue];
}

- (BOOL)doubleWidthForNonASCIICharacters;
{
    return [[_params objectForKey:kITSessionDoubleWidth] boolValue];
}

- (BOOL)deleteKeySendsBackspace;
{
    return [[_params objectForKey:kITSessionDeleteKeyIsBackspace] boolValue];
}

- (NSColor*)foreColor;
{
    return [_params objectForKey:kITSessionForeColor];
}

- (NSColor*)backColor;
{
    return [_params objectForKey:kITSessionBackColor];
}

- (NSColor*)selectionColor;
{
    return [_params objectForKey:kITSessionSelectionColor];
}

- (NSColor*)boldColor;
{
    return [_params objectForKey:kITSessionBoldColor];
}

- (NSColor*)ANSIBlackColor;
{
    return [_params objectForKey:kITSessionANSIBlackColor];
}

- (NSColor*)ANSIHilightBlackColor;
{
    return [_params objectForKey:kITSessionANSIHiBlackColor];
}

- (NSColor*)ANSIRedColor;
{
    return [_params objectForKey:kITSessionANSIRedColor];
}

- (NSColor*)ANSIHilightRedColor;
{
    return [_params objectForKey:kITSessionANSIHiRedColor];
}

- (NSColor*)ANSIGreenColor;
{
    return [_params objectForKey:kITSessionANSIGreenColor];
}

- (NSColor*)ANSIHilightGreenColor;
{
    return [_params objectForKey:kITSessionANSIHiGreenColor];
}

- (NSColor*)ANSIYellowColor;
{
    return [_params objectForKey:kITSessionANSIYellowColor];
}

- (NSColor*)ANSIHilightYellowColor;
{
    return [_params objectForKey:kITSessionANSIHiYellowColor];
}

- (NSColor*)ANSIBlueColor;
{
    return [_params objectForKey:kITSessionANSIBlueColor];
}

- (NSColor*)ANSIHilightBlueColor;
{
    return [_params objectForKey:kITSessionANSIHiBlueColor];
}

- (NSColor*)ANSIMagentaColor;
{
    return [_params objectForKey:kITSessionANSIMagentaColor];
}

- (NSColor*)ANSIHilightMagentaColor;
{
    return [_params objectForKey:kITSessionANSIHiMagentaColor];
}

- (NSColor*)ANSICyanColor;
{
    return [_params objectForKey:kITSessionANSICyanColor];
}

- (NSColor*)ANSIHilightCyanColor;
{
    return [_params objectForKey:kITSessionANSIHiCyanColor];
}

- (NSColor*)ANSIWhiteColor;
{
    return [_params objectForKey:kITSessionANSIWhiteColor];
}

- (NSColor*)ANSIHilightWhiteColor;
{
    return [_params objectForKey:kITSessionANSIHiWhiteColor];
}

@end

@implementation ITSessionDesc (Private)

- (void)setParams:(NSDictionary*)dictionary;
{
    [_params release];
    _params = [[NSMutableDictionary dictionaryWithDictionary:dictionary] retain];
}

+ (NSDictionary*)addMissingKeys:(NSDictionary*)inDictionary;
{
    NSMutableDictionary* result=nil;
    
    if (inDictionary)
    {
        result = [NSMutableDictionary dictionaryWithDictionary:inDictionary];
        
        NSDictionary *defaults = [self defaultSessionParam];
        NSArray *keys = [defaults allKeys];
        NSEnumerator *enumerator = [keys objectEnumerator];
        NSString* key;
        
        while (key = [enumerator nextObject])
        {
            // if key not found, add it
            if (![result objectForKey:key])
                [result setObject:[defaults objectForKey:key] forKey:key];
        }
    }
    else
        result = [NSMutableDictionary dictionaryWithDictionary:[self defaultSessionParam]];
    
    return result;
}

+ (NSColor *)lighten:(NSColor *)aColor;
{
    float hue, saturation, brightness, alpha;
    [[aColor colorUsingColorSpaceName:NSCalibratedRGBColorSpace] getHue:&hue saturation:&saturation brightness:&brightness alpha:&alpha];

    brightness = MIN(1.0, brightness + 0.3);
    return [NSColor colorWithCalibratedHue:hue saturation:saturation brightness:brightness alpha:alpha];
}

+ (NSDictionary *)defaultSessionParam;
{
    static NSDictionary *result=nil;
    
    if (!result)
    {
        NSColor* blackColor = [self lighten:[NSColor blackColor]];
        NSColor* redColor = [self lighten:[NSColor redColor]];
        NSColor* greenColor = [self lighten:[NSColor greenColor]];
        NSColor* yellowColor = [self lighten:[NSColor yellowColor]];
        NSColor* magentaColor = [self lighten:[NSColor magentaColor]];
        NSColor* cyanColor = [self lighten:[NSColor cyanColor]];
        NSColor* blueColor = [self lighten:[NSColor blueColor]];
        
        NSFont* font = [NSFont fontWithName:@"Monaco" size:10];
        NSFont* nafont = [NSFont fontWithName:@"Osaka-Mono" size:11];

        if (!font)
            font = [NSFont userFixedPitchFontOfSize:10];
        if (!nafont)
            nafont = [NSFont userFontOfSize:11];
        
        result = [[NSDictionary alloc] initWithObjectsAndKeys:
            NSLocalizedStringFromTableInBundle(@"Default", @"CocoaTechTerminal", [NSBundle bundleForClass:[self class]], @""), kITSessionName,

            [ITSessionDesc defaultLoginCommand], kITSessionCommand,
            
            [NSNumber numberWithUnsignedInt:1], kITSessionEncoding,
            
            @"vt100", kITSessionTerminalType,
            [@"~" stringByExpandingTildeInPath], kITSessionDirectory,
            
            font, kITSessionFont,
            nafont, kITSessionNAFont,
            
            [NSNumber numberWithBool:NO],kITSessionAntiIdle,
            [NSNumber numberWithUnsignedInt:0],kITSessionAICode,
            [NSNumber numberWithBool:YES],kITSessionAutoClose,
            [NSNumber numberWithBool:NO],kITSessionDoubleWidth,
            
            [NSNumber numberWithBool:NO],kITSessionDeleteKeyIsBackspace,
            
            // SNG trying to fix a bug where the cursor doesn't blink unless there is an alpha component
            [[NSColor whiteColor] colorWithAlphaComponent:.99], kITSessionForeColor,
            [[NSColor blackColor] colorWithAlphaComponent:.9], kITSessionBackColor,
            [NSColor colorWithCalibratedRed:0.45f green:0.5f blue:0.55f alpha:1.0f], kITSessionSelectionColor,
            [NSColor colorWithCalibratedRed:0.6f green:0.7f blue:1.0f alpha:.9f], kITSessionBoldColor,
            
            blackColor, kITSessionANSIBlackColor,
            [self highlightColor:blackColor], kITSessionANSIHiBlackColor,
            
            redColor, kITSessionANSIRedColor,
            [self highlightColor:redColor], kITSessionANSIHiRedColor,
            
            greenColor, kITSessionANSIGreenColor,
            [self highlightColor:greenColor], kITSessionANSIHiGreenColor,
            
            yellowColor, kITSessionANSIYellowColor,
            [self highlightColor:yellowColor], kITSessionANSIHiYellowColor,
            
            blueColor, kITSessionANSIBlueColor,
            [self highlightColor:blueColor], kITSessionANSIHiBlueColor,
            
            magentaColor, kITSessionANSIMagentaColor,
            [self highlightColor:magentaColor], kITSessionANSIHiMagentaColor,
            
            cyanColor, kITSessionANSICyanColor,
            [self highlightColor:cyanColor], kITSessionANSIHiCyanColor,
            
            [NSColor whiteColor], kITSessionANSIWhiteColor,
            [self highlightColor:[NSColor whiteColor]], kITSessionANSIHiWhiteColor,
            
            NULL];
    }
    
    return result;
}

+ (NSColor *)highlightColor:(NSColor *)color
{
    color=[color colorUsingColorSpaceName:NSCalibratedRGBColorSpace];
    
    if ([color brightnessComponent] > 0.5)
    {
        if ([color brightnessComponent] > 0.81) 
        {
            color=[NSColor colorWithCalibratedHue:[color hueComponent]
                                       saturation:[color saturationComponent]
                                       brightness:[color brightnessComponent]-0.3
                                            alpha:[color alphaComponent]];
        }
        else 
        {
            color=[NSColor colorWithCalibratedHue:[color hueComponent]
                                       saturation:[color saturationComponent]
                                       brightness:[color brightnessComponent]+0.3
                                            alpha:[color alphaComponent]];
        }
    }
    else 
    {
        if ([color brightnessComponent] > 0.19) 
        {
            color=[NSColor colorWithCalibratedHue:[color hueComponent]
                                       saturation:[color saturationComponent]
                                       brightness:[color brightnessComponent]-0.3
                                            alpha:[color alphaComponent]];
        }
        else 
        {
            color=[NSColor colorWithCalibratedHue:[color hueComponent]
                                       saturation:[color saturationComponent]
                                       brightness:[color brightnessComponent]+0.3
                                            alpha:[color alphaComponent]];
        }
    }
    
    return color;
}

@end

// ==============================================================================

@implementation ITMutableSessionDesc

- (id)init;
{
    self = [super init];
        
    return self;
}

- (void)encodeWithCoder:(NSCoder *)aCoder;
{
    [super encodeWithCoder:aCoder];
}

- (id)initWithCoder:(NSCoder *)aDecoder;
{
    self = [super initWithCoder:aDecoder];
        
    return self;
}

- (void)dealloc;
{
    [super dealloc];
}

- (void)setName:(NSString*)set;
{
    [_params setObject:set forKey:kITSessionName];
}

- (void)setCommand:(NSString*)set;
{
    [_params setObject:set forKey:kITSessionCommand];
}

- (void)setEncoding:(unsigned)set;
{
    [_params setObject:[NSNumber numberWithUnsignedInt:set] forKey:kITSessionEncoding];
}

- (void)setTerminalType:(NSString*)set;
{
    [_params setObject:set forKey:kITSessionTerminalType];
}

- (void)setDirectory:(NSString*)set;
{
    [_params setObject:set forKey:kITSessionDirectory];
}

- (void)setFont:(NSFont*)set;
{
    [_params setObject:set forKey:kITSessionFont];
}

- (void)setNonASCIIFont:(NSFont*)set;
{
    [_params setObject:set forKey:kITSessionNAFont];
}

- (void)setIdleKeepAliveEnabled:(BOOL)set;
{
    [_params setObject:[NSNumber numberWithBool:set] forKey:kITSessionAntiIdle];
}

- (void)setIdleKeepAliveCharacterCode:(unsigned char)set;
{
    [_params setObject:[NSNumber numberWithUnsignedInt:set] forKey:kITSessionAICode];
}

- (void)setCloseSessionWhenEnds:(BOOL)set;
{
    [_params setObject:[NSNumber numberWithBool:set] forKey:kITSessionAutoClose];
}

- (void)setDoubleWidthForNonASCIICharacters:(BOOL)set;
{
    [_params setObject:[NSNumber numberWithBool:set] forKey:kITSessionDoubleWidth];
}

- (BOOL)deleteKeySendsBackspace;
{
    return [[_params objectForKey:kITSessionDeleteKeyIsBackspace] boolValue];
}

- (void)setDeleteKeySendsBackspace:(BOOL)set;
{
    [_params setObject:[NSNumber numberWithBool:set] forKey:kITSessionDeleteKeyIsBackspace];
}

- (void)setForeColor:(NSColor*)set;
{
    // SNG trying to fix a bug where the cursor doesn't blink unless there is an alpha component
    if ([set alphaComponent] == 1.0)
        set = [set colorWithAlphaComponent:.99];

    [_params setObject:set forKey:kITSessionForeColor];
}

- (void)setBackColor:(NSColor*)set;
{
    [_params setObject:set forKey:kITSessionBackColor];
}

- (void)setSelectionColor:(NSColor*)set;
{
    [_params setObject:set forKey:kITSessionSelectionColor];
}

- (void)setBoldColor:(NSColor*)set;
{
    [_params setObject:set forKey:kITSessionBoldColor];
}

- (void)setANSIBlackColor:(NSColor*)set;
{
    [_params setObject:set forKey:kITSessionANSIBlackColor];
}

- (void)setHighlightANSIBlackColor:(NSColor*)set;
{
    [_params setObject:set forKey:kITSessionANSIHiBlackColor];
}

- (void)setANSIRedColor:(NSColor*)set;
{
    [_params setObject:set forKey:kITSessionANSIRedColor];
}

- (void)setHighlightANSIRedColor:(NSColor*)set;
{
    [_params setObject:set forKey:kITSessionANSIHiRedColor];
}

- (void)setANSIGreenColor:(NSColor*)set;
{
    [_params setObject:set forKey:kITSessionANSIGreenColor];
}

- (void)setHighlightANSIGreenColor:(NSColor*)set;
{
    [_params setObject:set forKey:kITSessionANSIHiGreenColor];
}

- (void)setANSIYellowColor:(NSColor*)set;
{
    [_params setObject:set forKey:kITSessionANSIYellowColor];
}

- (void)setHighlightANSIYellowColor:(NSColor*)set;
{
    [_params setObject:set forKey:kITSessionANSIHiYellowColor];
}

- (void)setANSIBlueColor:(NSColor*)set;
{
    [_params setObject:set forKey:kITSessionANSIBlueColor];
}

- (void)setHighlightANSIBlueColor:(NSColor*)set;
{
    [_params setObject:set forKey:kITSessionANSIHiBlueColor];
}

- (void)setANSIMagentaColor:(NSColor*)set;
{
    [_params setObject:set forKey:kITSessionANSIMagentaColor];
}

- (void)setHighlightANSIMagentaColor:(NSColor*)set;
{
    [_params setObject:set forKey:kITSessionANSIHiMagentaColor];
}

- (void)setANSICyanColor:(NSColor*)set;
{
    [_params setObject:set forKey:kITSessionANSICyanColor];
}

- (void)setHighlightANSICyanColor:(NSColor*)set;
{
    [_params setObject:set forKey:kITSessionANSIHiCyanColor];
}

- (void)setANSIWhiteColor:(NSColor*)set;
{
    [_params setObject:set forKey:kITSessionANSIWhiteColor];
}

- (void)setHighlightANSIWhiteColor:(NSColor*)set;
{
    [_params setObject:set forKey:kITSessionANSIHiWhiteColor];
}

@end

